﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using WCBG.ToolsForUnity.Tools;

public class DrawTrainNumberPart : StudyMathBasePart
{


    private const string scenePath = StudyPath.math_drawtrain_scene;
    private const string trainHeadPath = StudyPath.math_trainHeadPath;    // 火车头
    private const string trainNodeBluePath = StudyPath.math_trainNodeBluePath;    // 蓝色车厢
    private const string trainNodeBlue_Line_Path = StudyPath.math_trainNodeBlue_Line_Path;    // 蓝色虚线车厢
    private const string trainNodeGreenPath = StudyPath.math_trainNodeGreenPath;    // 绿色车厢

    private Transform m_scene;    // 场景目标
    private Transform m_trainHead;    // 火车头
    private TrainNodeActor m_dragTrainNodeActor;    // 当前拖动的火车车厢
    private GameAudioSource m_currentAudio;
    private GameAudioSource m_trainLoopAudio;   // 火车循环跑动音效

    private Vector3 m_dragStartPoint;    // 拖动的偏移

    private int m_trainNumber;    // 选择的火车数量
    private int m_trainNodeIndex;    // 当前拖动的火车车厢
    private int m_loopHintID;    // 无操作提示

    private readonly float checkNodeDragMinDis = 90f;    // 判断距离
    private readonly float trainMoveInTime = 5;    // 火车头进入时间
    private readonly float trainMoveOutTime = 4;    // 火车头离开时间
    private readonly float trainUpDownIntervalTime = 2;    // 火车头跳动间隔时间
    private float trainUpDownAddTime;

    private bool m_bIsDrawing;    // 是否正在写数字
    private bool m_bIsDrawComplete;    // 是否完成画数字
    private bool m_bCheckTrainHeadUpDown;    // 检测火车头跳动
    private bool m_bLockInput;

    private List<Transform> m_pathList = new List<Transform>();    // 弯道path信息
    private List<Transform> m_trainBornList = new List<Transform>();    // 火车厢出生位置信息
    private List<TrainNodeActor> m_trainNodeList = new List<TrainNodeActor>();    // 生成的火车厢list
    private List<TrainNodeActor> m_trainNodeDragList = new List<TrainNodeActor>();    // 可拖动的火车厢list
    private List<Transform> m_lineTrainNodeList = new List<Transform>();    // 生成的虚线车厢list


    protected override void OnPartStart(params object[] paramArray)
    {
        base.OnPartStart(paramArray);
        Debug.LogError("--------------------:DrawTrainNumberPart OnPartStart");

        // 初始化数值设置   ==========================

        m_trainNumber = (int)paramArray[0];
        m_trainNodeIndex = 0;
        m_bIsDrawing = false;
        m_bCheckTrainHeadUpDown = false;
        m_bIsDrawComplete = false;
        m_bLockInput = true;
        // ======================================================

        m_scene = CreateScene(scenePath);

        InitTrainInfo();
        CreateTrainHead();
        CreateTrainNode();
        SetAllTrainNodeCollider(false);
        SetAllTrainNodeActive(false);

        m_trainHead.position = m_pathList[0].position;
        TrainHeadActor trainMono = m_trainHead.GetComponent<TrainHeadActor>();
        trainMono.CrossFade(TrainHeadActor.AnimatorNameEnum.Move, 0.3f);
        trainMono.PlayEffect(StudyPath.math_traineffect_in);
        m_trainLoopAudio = this.PlayAudioEx(StudyAudioName.t_11002, true); 

        AddTimer(trainMoveInTime - 0.5f, () => {

            if (m_trainLoopAudio != null) m_trainLoopAudio.Stop();
            m_trainLoopAudio = null;
            this.PlayAudioEx(StudyAudioName.t_11003);
            trainMono.CrossFade(TrainHeadActor.AnimatorNameEnum.Static, 0.1f);
        });
        trainMono.MovePath(GetPath(0, m_pathList.Count - 4), trainMoveInTime, () =>
        {
            trainMono.ClearEffect();
            trainMono.PlayStopEffect(StudyPath.math_traineffect_stop);

            m_bCheckTrainHeadUpDown = true;
            trainMono.PlayHintEffect(StudyPath.math_traineffect_hint);
            Debug.Log("--------------------: 火车头到达");
        });
    }


    protected override void OnPartExit()
    {
        base.OnPartExit();

        m_bIsDrawing = false;
        m_scene = null;
        m_trainHead = null;
        m_dragTrainNodeActor = null;
        m_pathList.Clear();
        m_trainBornList.Clear();
        m_trainNodeList.Clear();
        m_trainNodeDragList.Clear();
        m_lineTrainNodeList.Clear();
        if (m_trainLoopAudio != null) m_trainLoopAudio.Stop();
        m_trainLoopAudio = null;

        InputTimerManager.Instance.RemoveTimerNoInput(m_loopHintID);
    }

    protected override void OnPartUpdate()
    {
        if (m_bCheckTrainHeadUpDown)
        {
            trainUpDownAddTime += Time.deltaTime;
            if (trainUpDownAddTime > trainUpDownIntervalTime)
            {
                trainUpDownAddTime = 0;

                if (m_bIsDrawing)
                    return;
                TrainHeadActor trainMono = m_trainHead.GetComponent<TrainHeadActor>();
                trainMono.CrossFade(TrainHeadActor.AnimatorNameEnum.UpAndDown, 0.01f);
                this.PlayAudioEx(StudyAudioName.t_11005);
            }
        }
    }

    protected override void OnMouseDown()
    {
        Transform target = FTools.GetRaycastHitTargetByMousePoint();
        if (target == null)
            return;

        if (target.GetComponent<TrainHeadActor>() == null && target.GetComponent<TrainNodeActor>() == null && target.gameObject.layer != (int)EGameLayerMask.Floor)
        {
            target.AddComponentEx<StudyFixedActor>().CrossFade(StudyFixedActor.AnimatorNameEnum.Jump, 0.01f);
            return;
        }

        if (!m_bIsDrawComplete)
        {
            TrainHeadActor trainMono = target.GetComponent<TrainHeadActor>();
            if (trainMono != null && !m_bIsDrawing && m_bCheckTrainHeadUpDown)
            {
                DrawNumber();
            }
            return;
        }

        TrainNodeActor trainNode = target.GetComponent<TrainNodeActor>();
        if (trainNode != null && !trainNode.IsComplete)
        {
            //if (m_bLockInput)
            //{
            //    trainNode.CrossFade(TrainNodeActor.AnimatorNameEnum.RightAneLeft, 0.01f);
            //    return;
            //}
            if (m_currentAudio != null)
            {
                m_currentAudio.Stop();
                m_currentAudio = null;
            } 
            DragTargetStart(trainNode);
        }
    }

    protected override void OnMouseHover()
    {
        if (m_dragTrainNodeActor != null)
        {
            RaycastHit hit;
            if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 100000))
            {
                Transform hitTarget = hit.transform;
                if (hitTarget.GetComponent<TrainHeadActor>() == null && hitTarget.GetComponent<TrainNodeActor>() == null)
                {
                    Vector3 newPoint = hit.point;
                    //newPoint.y = m_dragTrainNode.position.y;
                    //m_dragTrainNode.position = newPoint;
                    Vector3 offsetDir = newPoint - m_dragStartPoint;
                    m_dragStartPoint = newPoint;
                    m_dragTrainNodeActor.transform.position += offsetDir;

                    Transform node = GetTrainNode(m_trainNodeIndex);
                    if (node != null)
                    {
                        float distance = Vector3.Distance(m_dragTrainNodeActor.transform.position, node.position);
                        //Debug.Log("distance:" + distance);
                        if (distance < checkNodeDragMinDis)
                        {
                            m_trainNodeDragList.Remove(m_dragTrainNodeActor);
                            DragTargetComplete(node.position, node.rotation);
                            DragNextTrain();
                        }
                    }
                    else
                    {
                        Debug.LogError("获取目标失败！");
                    }
                }
            }
        }
    }

    protected override void OnMouseUp()
    {
        if (m_dragTrainNodeActor != null)
        {
            DragTargetEnd();
        }
    }

    private void DragTargetStart(TrainNodeActor target)
    {
        //Debug.Log("----------: DragTargetStart! target:" + target.name);
        m_dragTrainNodeActor = target;
        SetAllTrainNodeCollider(false);

        RaycastHit hit;
        if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 100000))
        {
            m_dragStartPoint = hit.point;
        }
    }

    private void DragTargetEnd()
    {
        if (m_dragTrainNodeActor == null)
            return;
        SetAllTrainNodeCollider(true);

        m_dragTrainNodeActor.ResetStartPositionAndRotation();
        //PlayMathAudio(StudyAudioName.TrainNodeSouAudio);
        this.PlayAudioEx(StudyAudioName.t_11013);
        m_dragTrainNodeActor = null;
    }

    private void DragTargetComplete(Vector3 toPosition, Quaternion toRotation)
    {
        float time = 0.2f;
        m_dragTrainNodeActor.SetNodeNumber(m_trainNodeIndex);
        m_dragTrainNodeActor.EndDrag(toPosition, toRotation, time);
        //PlayMathAudio(StudyAudioName.TrainNodeSouAudio);
        GameAudioSource audio = this.PlayAudioEx(StudyAudioName.t_11013);
        int index = m_trainNodeIndex;
        AddTimer(audio.Length, () => {
            this.PlayAudioEx(StudyAudioName.t_12006 + (uint)index);
        });
        int currentIndex = m_trainNodeIndex;
        int nextIndex = m_trainNodeIndex + 1;
        AddTimer(time - 0.1f, () =>
        {
            SetLineTrainActive(currentIndex, false);
            SetLineTrainActive(nextIndex, true);
            SetAllTrainNodeCollider(true);
        });
        m_dragTrainNodeActor = null;
    }

    private void DragNextTrain()
    {
        m_trainNodeIndex++;
        if (m_trainNodeIndex >= m_trainNumber)
        {
            DragTrainComplete();
        }
    }

    private void DragTrainComplete()
    {
        Debug.Log("所有火车都已经连接完成！");
        
        AddTimer(2000, () =>
        {
            TrainHeadActor trainHead = m_trainHead.GetComponent<TrainHeadActor>();
            trainHead.CrossFade(TrainHeadActor.AnimatorNameEnum.Zoom, 0.01f);
            GameAudioSource audio = this.PlayAudioEx(StudyAudioName.t_11001);
            float waitTime = audio.Length == 0 ? 2 : audio.Length;
            AddTimer(waitTime, () =>
            {
                Vector3[] trainHeadPath = GetPath(m_pathList.Count - 5, m_pathList.Count);

                float maxMoveTime = trainMoveOutTime;
                float pathDis = GetPathDistance(trainHeadPath);
                float timeDis = pathDis / maxMoveTime;
                //TrainHeadActor trainHead = m_trainHead.GetComponent<TrainHeadActor>();
                trainHead.transform.position = trainHeadPath[0];
                trainHead.MovePath(trainHeadPath, maxMoveTime);
                trainHead.CrossFade(TrainHeadActor.AnimatorNameEnum.Move, 0.01f);
                trainHead.PlayEffect(StudyPath.math_traineffect_out);
                //GameAudioSource audio1 = PlayMathAudio(StudyAudioName.TrainMoveAudio);
                m_trainLoopAudio = this.PlayAudioEx(StudyAudioName.t_11002, true);

                foreach (TrainNodeActor train in m_trainNodeList)
                {
                    Vector3[] nodePath = GetPath(m_pathList.Count - train.Number - 6, m_pathList.Count);
                    float duration = GetPathDistance(nodePath) / timeDis;
                    maxMoveTime = duration > maxMoveTime ? duration : maxMoveTime;
                    //Debug.Log("duration:"+ duration);
                    train.transform.position = nodePath[0];
                    train.MovePath(nodePath, duration);
                    train.CrossFade(TrainNodeActor.AnimatorNameEnum.Move, 0.01f);
                }

                AddTimer(maxMoveTime, () =>
                {
                    Debug.Log("游戏完成！");
                    m_trainLoopAudio.Stop();
                    m_trainLoopAudio = null;
                    OnPartComplete(true, m_trainNumber);
                        //PlayMathAudio(StudyAudioName.SucceedAudio);
                        this.PlayAudioEx(StudyAudioName.t_11017);
                });
            });
        });
    }

    private void DrawNumber()
    {
        Debug.Log(" --------------: 开始画数字：" + m_trainNumber);

        m_bIsDrawing = true;

        WindowManager.Instance.CloseWindow(WinNames.MathNumberPanel);
        WindowManager.Instance.OpenWindow(WinNames.DrawNumberPanel, EWindowFadeEnum.ScaleIn);
        DrawNumberWindow.Instance.StartDrawNumber(m_trainNumber, (isComplete) =>
        {
            WindowManager.Instance.OpenWindow(WinNames.MathNumberPanel);
            if (isComplete)
            {
                WindowManager.Instance.CloseWindow(WinNames.DrawNumberPanel);
                TrainHeadActor trainMono = m_trainHead.GetComponent<TrainHeadActor>();
                trainMono.ClearAllEffect();
                DrawNumberComplete();
            }
            m_bIsDrawing = false;
            Debug.Log(" --------------: 画数字退出");
        });
    }

    private void DrawNumberComplete()
    {
        Debug.Log(" --------------: 画数字完成");

        m_trainHead.GetComponent<TrainHeadActor>().SetHighTexture(true);
        m_bCheckTrainHeadUpDown = false;
        SetAllTrainNodeCollider(true);
        SetAllTrainNodeActive(true);
        //SetAllLineTrainNodeActive(true);
        SetLineTrainActive(0, true);
        m_bIsDrawComplete = true;

        m_currentAudio = this.PlayAudioEx(StudyAudioName.t_12016);
        AddTimer(m_currentAudio.Length, () =>
        {
            if (m_currentAudio != null)
            {
                OnHint(0);
            }
            m_currentAudio = null;
            //m_bLockInput = false;
            m_loopHintID = InputTimerManager.Instance.AddTimerNoInput(5, true, OnHint);
        });

    }

    private void OnHint(int seq)
    {
        if (m_trainNodeDragList.Count > 0)
        {
            m_trainNodeDragList[Random.Range(0, m_trainNodeDragList.Count)].CrossFade(TrainNodeActor.AnimatorNameEnum.RightAneLeft, 0.01f);
            this.PlayAudioEx(StudyAudioName.t_11022);
        }
    }

    private void InitTrainInfo()
    {
        List<string> pathNameList = new List<string>() {
            "Path/Train0",
            "Path/Train1",
            "Path/Train2",
            "Path/Train3",
            "Path/Train4",
            "Path/Train5",
            "Path/Train6",
            "Path/Train7",
            "Path/Train8",
            "Path/Train9",
            "Path/Train10",
            "Path/Train11",
            "Path/Train_Head",
            "Path/Train13",
            "Path/Train14",
            "Path/Train15",
            "Path/Train16"
        };

        for (int i = 0; i < pathNameList.Count; i++)
        {
            string str = pathNameList[i];
            Transform target = m_scene.Find(str);
            m_pathList.Add(target);
        }

        List<string> trainList = new List<string>() {
            "Trains/Train (1)",
            "Trains/Train (2)",
            "Trains/Train (3)",
            "Trains/Train (4)",
            "Trains/Train (5)",
            "Trains/Train (6)",
            "Trains/Train (7)",
            "Trains/Train (8)",
            "Trains/Train (9)",
            "Trains/Train (10)"
        };
        for (int i = 0; i < trainList.Count; i++)
        {
            string str = trainList[i];
            Transform target = m_scene.Find(str);
            m_trainBornList.Add(target);
        }

    }

    private void CreateTrainHead()
    {
        string path = trainHeadPath;

        GameObject go = Instantiate(path, true);
        if (go != null)
        {
            m_trainHead = go.transform;
            TrainHeadActor trainMono = go.AddComponent<TrainHeadActor>();

            if (m_trainNumber % 2 == 0)
            {
                trainMono.SetTrainRedTexture();
            }
            else
            {
                trainMono.SetTrainYellowTexture();
            }

            trainMono.Initialize(m_trainNumber, false);
        }
    }

    private void CreateTrainNode()
    {
        Resource res = ResourceManager.Instance.GetResource(trainNodeBluePath, typeof(GameObject), enResourceType.ScenePrefab);
        if (res.m_content == null)
        {
            Debug.LogError("Load faild!path:" + trainNodeBluePath);
            return;
        }
        Resource res2 = ResourceManager.Instance.GetResource(trainNodeGreenPath, typeof(GameObject), enResourceType.ScenePrefab);
        if (res2.m_content == null)
        {
            Debug.LogError("Load faild!path:" + trainNodeGreenPath);
            return;
        }
        GameObject prefabBlue = res.m_content as GameObject;
        GameObject prefabGreen = res2.m_content as GameObject;

        for (int i = 0; i < m_trainNumber; i++)
        {
            Transform target = null;
            if (i % 2 == 0)
            {
                target = Instantiate(prefabBlue, true).transform;
            }
            else
            {
                target = Instantiate(prefabGreen, true).transform;
            }

            //target.position = m_trainBornList[i].position;
            //target.rotation = m_trainBornList[i].rotation;
            TrainNodeActor node = target.gameObject.AddComponent<TrainNodeActor>();
            //node.Initialize(m_trainBornList[i].position, m_trainBornList[i].rotation);
            node.Initialize(m_trainBornList[i].position, Quaternion.Euler(0, Random.Range(180, 360), 0));
            m_trainNodeList.Add(node);
            m_trainNodeDragList.Add(node);

            Transform _lineNodeTrain = Instantiate(trainNodeBlue_Line_Path, true).transform;

            Transform _nodePoint = GetTrainNode(i);
            if (_nodePoint != null)
            {
                _lineNodeTrain.position = _nodePoint.position;
                _lineNodeTrain.rotation = _nodePoint.rotation;
            }
            _lineNodeTrain.SetActive(false);
            m_lineTrainNodeList.Add(_lineNodeTrain);
        }

    }

    private void SetLineTrainActive(int index, bool value)
    {
        if (index < m_lineTrainNodeList.Count)
        {
            m_lineTrainNodeList[index].SetActive(value);
        }
    }

    private Vector3[] GetPath(int start, int end)
    {
        List<Vector3> list = new List<Vector3>();

        for (int i = start; i < end; i++)
        {
            list.Add(m_pathList[i].position);
        }

        return list.ToArray();
    }

    private Transform GetTrainNode(int index)
    {
        int idx = m_pathList.Count - index - 6;
        return m_pathList[idx];
    }

    private float GetPathDistance(Vector3[] path)
    {
        float dis = 0;
        for (int i = 0; i < path.Length - 1; i++)
        {
            dis += Vector3.Distance(path[i], path[i + 1]);
        }
        return dis;
    }

    private void SetAllTrainNodeCollider(bool value)
    {
        foreach (TrainNodeActor mono in m_trainNodeList)
        {
            mono.GetComponent<BoxCollider>().enabled = value;
        }
    }

    private void SetAllTrainNodeActive(bool value)
    {
        foreach (TrainNodeActor mono in m_trainNodeList)
        {
            mono.gameObject.SetActive(value);
        }
    }

    private void SetAllLineTrainNodeActive(bool value)
    {
        foreach (Transform target in m_lineTrainNodeList)
        {
            target.SetActive(value);
        }
    }


}
